#include <iostream>
#include <unistd.h>
#include <cerrno>  //error.h
#include <cstring>  //string.h
#include <sys/wait.h>
#include <sys/types.h>
#include <string>

const int size=1024;

std::string getothermassage()
{
    static int cnt;
    std::string massageid = std::to_string(cnt); //to_string: string -> int   stoi: int -> string
    cnt++;
    pid_t self_id = getpid();
    std::string stringpid = std::to_string(self_id);

    std::string message="messageid: ";
    message += massageid;
    message += " my pid is ";
    message += stringpid;

    return message;
}

// 子进程写入
void SubProcessWrite(int wfd)
{
    std::string message = "i am child ";
    while(true)
    {
        std::string info = message + getothermassage();
        write(wfd, info.c_str(), info.size());

        sleep(1);
    }
}

// 父进程读取
void SubProcessRead(int rfd)
{
    char inbuffer[size];
    while(true)
    {
        ssize_t n =  read(rfd, inbuffer, sizeof(inbuffer) - 1);
        if(n > 0)
        {
            inbuffer[n] = '\0';
            std::cout<< "father get message: "<< inbuffer<< std::endl;
        }
    }
}

int main()
{
    // 1.创建管道
    int pipefd[2];
    int n = pipe(pipefd); // pipefd是输出型参数

    if(n!=0)
    {
        std::cout<<"errno: "<<errno<<": "<<"errstring"<<strerror(errno)<<std::endl;
        return 1;
    }
    // pipe fd[0]->r   pipefd[1]-w
    std::cout<<"pipefd[0]: "<<pipefd[0]<<",pipefd[1]: "<<pipefd[1]<<std::endl;

    sleep(1);

    // 2.创建子进程
    pid_t id = fork();
    if(id == 0)
    {
        //子进程 --- write
        // 3.关闭不需要的fd
        std::cout<<"子进程关闭了不需要的fd，准备发送消息"<<std::endl;
        sleep(1);

        close(pipefd[0]);
        
        SubProcessWrite(pipefd[1]);
        
        close(pipefd[1]);
        exit(0);
    }

    // 父进程 --- read
    // 3.关闭不需要的fd
    std::cout<<"父进程关闭了不需要的fd，准备接收消息"<<std::endl;
    sleep(1);

    close(pipefd[1]);
    
    SubProcessRead(pipefd[0]);

    close(pipefd[0]);

    pid_t rid = waitpid(id,nullptr,0);
    if(rid > 0)
    {
        std::cout<<"wait child process done"<<std::endl;
    }

    return 0;
}